//#include <NTDDK.h>
#include <ifs/wnet/ntifs.h>
//#include <wdm.h>

VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject);
NTSTATUS DriverEntry (
    IN PDRIVER_OBJECT pDriverObject,
    IN PUNICODE_STRING pRegistryPath	);
 SS_2F();

static ULONG EAX_2F = 0;
static ULONG ADDR_2E = 0;

#pragma alloc_text(init, DriverEntry)
#pragma alloc_text(page, DriverUnload)
#pragma alloc_text(page, SS_2F)

static 	PDEVICE_OBJECT dev_obj = NULL;

__declspec(naked) SS_2F()
{
	__asm{
		mov EAX_2F, eax;
		_asm _emit 0x0F;
		_asm _emit 0x35; //sysexit
		mov eax, ADDR_2E;
		jmp eax;
	cld
	push eax
	push ecx
	push edx
	push ds
	push es
	push fs

	pop fs
	pop es
	pop ds
	pop edx
	pop ecx
	pop eax
	iret
//		mov eax, 0x2f;
//		mov [EAX_2F], eax;
//		iret;
	};
/*
ignore_int:
	cld
	pushl %eax
	pushl %ecx
	pushl %edx
	push %ds
	push %es
	push %fs
	movl $(KERNEL_DS),%eax
	mov %ax,%ds
	mov %ax,%es
	mov %ax,%fs
	pushl $int_msg
	call _printk
	popl %eax
	pop %fs
	pop %es
	pop %ds
	popl %edx
	popl %ecx
	popl %eax
	iret
*/
}

#pragma pack(1)

typedef struct
{
    short limit;
	ULONG base;
} IDTR; // GDTR and IDTR format

typedef struct
{
	short offs_l;
	short sel;
	short attrib;
	short offs_h;
} DESC; 

#pragma pack()


static NTSTATUS ignore(IN struct _DEVICE_OBJECT *DeviceObject, IN struct _IRP *Irp)
{
	PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);

	IoCompleteRequest(Irp, IO_NO_INCREMENT);	
	return STATUS_SUCCESS;
}

static NTSTATUS interrupt_read(IN struct _DEVICE_OBJECT *DeviceObject, IN struct _IRP *Irp)
{
	PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
	IDTR testidt;
	DESC *desc;
	int i;
	
	__asm{
		sidt [testidt];
	};
	
	KdPrint(("interrupt %s: testidt[%x] limit = %hx, base = %x\n", __FUNCTION__, *(ULONG *)&testidt, testidt.limit, testidt.base));

	desc = (DESC *)testidt.base;
/*
	for (i = 0; i <= 32; ++i)
	{
		KdPrint(("interrupt %s: desc[%d] offs_h[%hx] offs_l[%hx] sel[%hx] attrib[%hx]\n",
				__FUNCTION__, i, desc[i].offs_h, desc[i].offs_l, desc[i].sel, desc[i].attrib));		
	}
*/
	i = 0x2e;
	KdPrint(("interrupt %s: desc[%d] offs_h[%hx] offs_l[%hx] sel[%hx] attrib[%hx]\n",
			__FUNCTION__, i, desc[i].offs_h, desc[i].offs_l, desc[i].sel, desc[i].attrib));		
	i = 0x31;
	KdPrint(("interrupt %s: desc[%d] offs_h[%hx] offs_l[%hx] sel[%hx] attrib[%hx]\n",
			__FUNCTION__, i, desc[i].offs_h, desc[i].offs_l, desc[i].sel, desc[i].attrib));		


	ADDR_2E = desc[0x2e].offs_h << 16 | desc[0x2e].offs_l;
	
	desc[0x31].attrib = 0xee00;
	desc[0x31].offs_h = (short)(((ULONG)SS_2F) >> 16);
	desc[0x31].offs_l = (short)(((ULONG)SS_2F) & 0xffff);

//	desc[0x31].offs_h = desc[0x2e].offs_h;
//	desc[0x31].offs_l = desc[0x2e].offs_l;
	KdPrint(("interrupt %s: desc[%d] offs_h[%hx] offs_l[%hx] sel[%hx] attrib[%hx]\n",
			__FUNCTION__, i, desc[i].offs_h, desc[i].offs_l, desc[i].sel, desc[i].attrib));			

	KdPrint(("interrupt %s: eax_2f = %x\n", __FUNCTION__, EAX_2F));
	IoCompleteRequest(Irp, IO_NO_INCREMENT);	
	return STATUS_SUCCESS;
}

VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject)
{
	if (dev_obj)
	{
		IoDeleteDevice(dev_obj);
		dev_obj = NULL;
	}
	KdPrint(("interrupt : %s \n", __FUNCTION__));	
}

NTSTATUS DriverEntry (
    IN PDRIVER_OBJECT pDriverObject,
    IN PUNICODE_STRING pRegistryPath	)
{
	NTSTATUS ret;
	UNICODE_STRING name, link_name;
	
	KdPrint(("interrupt : %s \n", __FUNCTION__));
	pDriverObject->DriverUnload = DriverUnload;

	pDriverObject->MajorFunction[IRP_MJ_CREATE] = ignore;
	pDriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = ignore;
	pDriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = ignore;
	pDriverObject->MajorFunction[IRP_MJ_READ] = interrupt_read;
	pDriverObject->MajorFunction[IRP_MJ_WRITE] = ignore;
	
	RtlInitUnicodeString(&name, L"\\FileSystem\\testint");
	ret = IoCreateDevice(pDriverObject, 0, &name, FILE_DEVICE_UNKNOWN, 0, FALSE, &dev_obj);
	if (ret != STATUS_SUCCESS) {
		KdPrint(("interrupt : %s : IoCreateDevice fail[0x%x]\n", __FUNCTION__, ret));
		return STATUS_SUCCESS;	
	}

	RtlInitUnicodeString(&link_name, L"\\??\\testint_link");
	IoDeleteSymbolicLink(&link_name);
	ret = IoCreateSymbolicLink(&link_name, &name);
	if (ret != STATUS_SUCCESS) {
		KdPrint(("interrupt : %s : IoCreateSymbolicLink fail[0x%x]\n", __FUNCTION__, ret));
		return STATUS_SUCCESS;	
	}
	
	SetFlag(dev_obj->Flags, DO_BUFFERED_IO );
	SetFlag(dev_obj->Characteristics, FILE_DEVICE_SECURE_OPEN );
    ClearFlag(dev_obj->Flags, DO_DEVICE_INITIALIZING);
	
	return STATUS_SUCCESS;
}


